package cn.tedu.csmallpassport.service.impl;

import cn.tedu.csmallpassport.ex.ServiceException;
import cn.tedu.csmallpassport.mapper.AdminMapper;
import cn.tedu.csmallpassport.mapper.AdminRoleMapper;
import cn.tedu.csmallpassport.pojo.dto.*;
import cn.tedu.csmallpassport.pojo.entity.Admin;
import cn.tedu.csmallpassport.pojo.entity.AdminRole;
import cn.tedu.csmallpassport.pojo.vo.AdminListItemVO;
import cn.tedu.csmallpassport.pojo.vo.AdminStandardVO;
import cn.tedu.csmallpassport.security.AdminDetails;
import cn.tedu.csmallpassport.service.AdminService;
import cn.tedu.csmallpassport.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
@Slf4j
public class AdminServiceImpl implements AdminService {

    @Autowired
    AdminMapper mapper;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    AuthenticationManager manager;
    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private Long durationInMinute;

    @Override
    public String login(AdminLoginInfoDTO adminLoginInfoDTO) {
        Authentication authentication = new UsernamePasswordAuthenticationToken(adminLoginInfoDTO.getUsername(),
                adminLoginInfoDTO.getPassword());
        Authentication authenticate = manager.authenticate(authentication);
        AdminDetails authorities = (AdminDetails) authenticate.getPrincipal();
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",authorities.getId());
        claims.put("username",authorities.getUsername());
        String authoritiesJsonString = JSON.toJSONString(authorities.getAuthorities());
        claims.put("authoritiesJsonString", authoritiesJsonString);

        String builder = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis()+ durationInMinute * 60 * 1000))
                .signWith(SignatureAlgorithm.HS256,secretKey)
                .compact();
//        SecurityContext context = SecurityContextHolder.getContext();
//        context.setAuthentication(authenticate);
        return builder;
    }

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        // 检查角色ID的数组中是否包含1号角色，如果包含，则抛出异常
        Long[] roleIds = adminAddNewDTO.getRoleIds();
        for (Long roleId : roleIds) {
            if (roleId == 1) {
                // 是：抛出异常
                String message = "添加管理员失败，非法访问！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
            }
        }
        Integer count = mapper.countByUsername(adminAddNewDTO.getUsername());
        if (count > 0) {
            String message = "添加管理员失败，用户名已经被占用！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
        }

        count = mapper.countByEmail(adminAddNewDTO.getEmail());
        if (count > 0) {
            String message = "添加管理员失败，邮箱已经被占用！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
        }

        count = mapper.countByPhone(adminAddNewDTO.getPhone());
        if (count > 0) {
            String message = "添加管理员失败，电话号码已经被占用！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
        }

        Admin amsAdmin = new Admin();
        BeanUtils.copyProperties(adminAddNewDTO,amsAdmin);
        amsAdmin.setLoginCount(0);
        String rawPassword = amsAdmin.getPassword();
        String endPassword = passwordEncoder.encode(rawPassword);
        amsAdmin.setPassword(endPassword);
        Integer insert = mapper.insert(amsAdmin);
        if (insert != 1){
            String message = "添加管理员失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_INSERT,message);
        }
        // 为新添加的管理员分配角色
        // 通过参数得到角色ID的数组
        // 基于角色ID的数组来创建List<AdminRole>
        List<AdminRole> adminRoleList = new ArrayList<>();
        for (Long roleId : roleIds) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(amsAdmin.getId());
            adminRole.setRoleId(roleId);
            adminRoleList.add(adminRole);
        }
        // 调用AdminRoleMapper对象的insertBatch()执行插入
        int rows = adminRoleMapper.insertBatch(adminRoleList);
        if (rows < 1) {
            String message = "添加管理员失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }

    }

    @Override
    public void delete(Long id)     {
        // 检查尝试删除的是否为1号管理员
        if (id == 1) {
            String message = "删除管理员失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        AdminStandardVO amsAdminVo = mapper.getStandardById(id);
        if (amsAdminVo == null) {
            String message = "删除管理员失败，用户不存在！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,message);
        }
        Integer integer = mapper.deleteById(id);
        if (integer != 1){
            String message = "删除管理员失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_DELETE,message);
        }
    }

    @Override
    public List<AdminListItemVO> list() {
        List<AdminListItemVO> list = mapper.list();
        Iterator<AdminListItemVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            AdminListItemVO item = iterator.next();
            if (item.getId() == 1) {
                iterator.remove();
                break;
            }
        }
        return list;
    }

    @Override
    public void disable(Long id) {
        updateEnable(id,0);
    }

    @Override
    public void enable(Long id) {
        updateEnable(id,1);
    }

    public void updateEnable(Long id,Integer enable){
        log.debug("id:{},enable:{}",id,enable);
        AdminStandardVO standardById = mapper.getStandardById(id);
        if (standardById.getEnable() == enable){
            return;
        }
        AdminUpdateDto adminUpdateDto = new AdminUpdateDto();
        adminUpdateDto.setEnable(enable);
        adminUpdateDto.setId(id);
        mapper.updateEnableBuId(adminUpdateDto);
    }

}
